local a = CreateFrame("Frame", "Snoopy", UIParent)

local _G = getfenv(0)
local GameTooltip, strsub = GameTooltip, strsub
local CheckInteractDistance, GetInventoryItemLink = CheckInteractDistance, GetInventoryItemLink
local UnitExists, UnitIsPlayer, UnitCanAttack = UnitExists, UnitIsPlayer, UnitCanAttack
local oInspectPaperDollFrame_OnShow, oInspectPaperDollItemSlotButton_Update

local cache = { }
local elap, schedule, text = 0, 0.25, nil
local UpdateAllData, UpdateUnit, UpdateNote

UnitPopupButtons.INSPECT.dist = 0  -- enables "Inspect" option in dropdown

a:Hide()
a:RegisterEvent("ADDON_LOADED")
a:SetScript("OnEvent", function(self, event, a1)
	if a1 ~= "Blizzard_InspectUI" then return end
	a:UnregisterEvent("ADDON_LOADED")
	a:SetScript("OnEvent", nil)
	InspectFrame:RegisterEvent("INSPECT_TALENT_READY")
	InspectFrame:SetScript("OnUpdate", nil)
	
	function UpdateAllData()  -- try to update all of the inspect window data
		InspectPaperDollFrame_OnShow()
		InspectPVPFrame_OnShow()
		InspectFrame_UpdateTalentTab()
		SetPortraitTexture(InspectFramePortrait, InspectFrame.unit)
	end
	function UpdateNote(note, timer)  -- inspect status text
		if note then
			elap, schedule = 0, timer
			text:SetText(note)
			a:Show()
		else
			text:SetText("")
			a:Hide()
		end
	end
	function UpdateUnit(unit)  -- update unit
		if not UnitIsPlayer(unit) then return end
		InspectFrame.unit = unit
		InspectNameText:SetText(UnitPVPName(unit))
		UpdateTitleText(unit, true)
		ShowUIPanel(InspectFrame)
		NotifyInspect(unit)
		UpdateAllData()
		if not UnitCanAttack("player", unit) then
			UpdateNote(not CheckInteractDistance(unit, 1) and "Out of Inspect Range", 0.25)
		else
			UpdateNote("Cannot Inspect PVP Enemy", 2)
		end
	end
	function UpdateTitleText(unit, reset)
		local gname, gtitle = GetGuildInfo(unit)
		local talenttext
		for i = 1, reset and 0 or GetNumTalentTabs(), 1 do
			local name, _, pts = GetTalentTabInfo(i, true)
			if not name then return end
			talenttext = format("%s%s%d %s ", talenttext or "", i~=1 and "/ " or "", pts, strsub(name, 1, 3))
		end
		InspectTitleText:SetFormattedText( (gname and "%s of <%s>\n%s") or "-%s%s\n%s", gtitle or "", gname or "", talenttext or "-" )
	end

	InspectFrame_Show = function(unit)
		if not UnitIsPlayer(unit) then return end
		PlaySound("igCharacterInfoOpen")
		UpdateUnit(unit)
	end
	
	InspectFrame_OnEvent = function(self, ev, a1)
		if not InspectFrame:IsShown() then return end
		local unit = InspectFrame.unit
		if ((ev == "PLAYER_TARGET_CHANGED" and unit == "target") or (ev == "PARTY_MEMBERS_CHANGED" and unit ~= "target")) and UnitExists(unit) then
			UpdateUnit(unit)
		elseif ev == "UNIT_PORTRAIT_UPDATE" and unit == a1 then
			SetPortraitTexture(InspectFramePortrait, unit)
			UpdateUnit(unit)
		elseif ev == "UNIT_NAME_UPDATE" and unit == a1 then
			InspectNameText:SetText(UnitPVPName(unit))
		elseif ev == "INSPECT_TALENT_READY" then
			UpdateTitleText(unit)
		end
	end
	
	oInspectPaperDollItemSlotButton_Update = InspectPaperDollItemSlotButton_Update
	InspectPaperDollItemSlotButton_Update = function(button, ...)
		oInspectPaperDollItemSlotButton_Update(button, ...)
		local unit = InspectFrame.unit
		if CheckInteractDistance(unit, 1) then
			cache[strsub(button:GetName(), 8)] = GetInventoryItemLink(unit, button:GetID())
		end
	end
	
	InspectPaperDollItemSlotButton_OnEnter = function(self)
		self = self or this
		local name = strsub(self:GetName(), 8)
		local unit = InspectFrame.unit
		GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
		if UnitExists(unit) and CheckInteractDistance(unit, 1) and GameTooltip:SetInventoryItem(unit, self:GetID()) then
		
		elseif cache[name] then  -- retrieved from cache
			GameTooltip:SetHyperlink(cache[name])
		else  -- empty slot
			GameTooltip:SetText((self.checkRelic and UnitHasRelicSlot(unit) and _G.RELICSLOT) or _G[strupper(name)])
		end
		CursorUpdate(self)
	end
	
	oInspectPaperDollFrame_OnShow = InspectPaperDollFrame_OnShow
	InspectPaperDollFrame_OnShow = function(...)
		if not UnitIsPlayer(InspectFrame.unit) then return end
		oInspectPaperDollFrame_OnShow(...)
	end
	
	InspectNameText:SetWidth(330)
	InspectTitleText:Show()
	InspectTitleText:SetText("")
	text = InspectFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
	text:SetPoint("TOP", InspectFrame, "TOP", 0, -1)
	text:SetAlpha(0.8)
	
	a:SetScript("OnUpdate", function(this, a1)
		elap = elap + a1
		if elap < schedule then return end
		elap = 0
		
		local unit = InspectFrame.unit
		if not UnitExists(unit) or schedule == 2 then 
			UpdateNote()
		elseif CheckInteractDistance(unit, 1) then
			NotifyInspect(unit)
			UpdateAllData()
			UpdateNote("Inspect Successful", 2)
		end
	end)
end)
